Repository navigation
test(contract): four drift fences — fragment identity, toolchain ceiling, SSID matcher table, clean-container lane - #775
Amperstrand wants to merge 1 commit into
Conversation
|
VERDICT: CHANGES-REQUESTED — all four fences exist, fail when their drift is planted, and the toolchain-ceiling criterion is sane for shipped modules, but one fence ships a runtime behavior change inside a On the brief's specific questions first:
Findings:
Hygiene: four commits = four fences, cleanly chunked; base is the current main tip; fragment is Freeze call: SPLIT. The three pure-CI fences (fragment identity, toolchain ceiling, clean-container lane) are freeze-compatible — land them. The |
…1/F4) cross-vectors/generate declared go 1.27.1 — an artifact of the dev toolchain that authored it, nothing the code needs. Lowered to 1.26.0 so the module runs under the repo's pinned toolchain and satisfies the ceiling #775 is about to gate (review: the right fix is lowering the directive, not weakening the fence — anyone regenerating vectors uses the pinned toolchain). Regeneration verified byte-identical (same sha256, no downstream churn). check-cross-vectors-sync.sh now also compiles the generator wherever go exists (the generator sits outside go-battery and the CI matrix; a broken generator would otherwise surface only at dev time). Named-loudly skipped in Go-less lanes by design. Refs #779 review (F1, F4)
d603797 to
c0a7327
Compare
The reader twin of check-ssid-format.sh: hasTollGateSSID's acceptance table becomes a committed fixture file (tests/contract/ ssid-naming-fixtures.txt) driven by both the Go unit test and tests/contract/check-ssid-naming.sh (structural class coverage + wiring + the behavioural go test). This fence pins the CONTRACT AS MAIN SATISFIES IT — both brands bare, case-insensitive (lowercase installer-era SSIDs still in the fleet), the double-'!' rejections, the anchored negatives — so it is green on main by construction and red on any regression. The single-'!'-decorated POSITIVE classes and the ssidDecoration wiring check land with #706's reader half (PR #839) — a feature-shaped runtime change split out of this PR per its review's freeze call. When #839 merges, the '!'-positive fixture lines and require_class entries return with it. Whitelabel fixtures carry the brand literal in the table's allowlisted home (rebrand gutter, same exemption as check-ssid-format.sh); Go source keeps assembling it from non-contiguous bytes. Refs #767, split per #775 review
|
All four findings actioned; head F1 — the split (the blocker). Done exactly as called: F2 — the #779 collision. Resolved from the #779 side, as you directed: F3 — known-issues openness. The gate now enforces the promise wherever a token exists (the GitHub lane): every entry's F4 — the omitted modules. The gate's header now names them where it lives: Bonus — fence 1's first live catch is main itself. Rebasing onto current main surfaced Full re-verification on the rebuilt head: fragments offline + online (11 fragments green), both verdicts harnesses (11 + 9 cases), toolchain parity green on the moved base, ssid-naming fence green against main's matcher, rebrand gutter green, both workflow twins YAML-valid, and the amended clean-container gate rehearsed end-to-end (1 tolerated known issue, 0 fatal, exit 0) including the new openness check. Freeze call accepted as ruled: this PR is now three pure-CI fences + a behavior-pinned fourth, all freeze-compatible; #839 carries the runtime delta and defaults post-0.6.0 unless the owner rules otherwise. |
…llGate#839 The reader tolerance (hasTollGateSSID trimming at most one leading '!' before the case-insensitive brand-prefix compare) is carried by OpenTollGate#839 (fix/706-ssid-reader-tolerance, split out of OpenTollGate#775). Both PRs modify src/wireless_gateway_manager/brands.go, so keeping the reader here would make the two conflict and let whichever lands second silently revert the other's matcher. One writer, one reader, no overlap. Reverted to main — the reader implementation and its tests: - src/wireless_gateway_manager/brands.go - src/wireless_gateway_manager/brands_test.go - src/wireless_gateway_manager/reseller_mode_test.go The last one is not a "brands*.go" file but is reader-side all the same: it adds a `!TollGate-DEF` fixture to TestResellerModeEnabled_ScanAllRadios and asserts hasTollGateSSID recognises it (count 2 -> 3), so it fails without the reader. Note for OpenTollGate#839: it does not carry that reseller-mode coverage, so the decorated-SSID-selected-as-upstream assertion still has to land somewhere. Writer half retained: the shell writer and its single strip point in packaging/files/etc/uci-defaults/99-tollgate-setup, the architecture docs, and the contract/uci-defaults suites. Net diff is now writer-only (no src/ changes at all). Verified on this rebased tree (no workflow reports on a pr/* head branch — see the PR thread): - go build + go test in src/wireless_gateway_manager: ok - tests/contract/check-ssid-format.sh: pass - tests/uci-defaults-device-code_test.sh: 89 passed, 0 failed - tests/uci-defaults-gatewayname-banner_test.sh: 21 passed, 0 failed - tests/uci-defaults-setup-marker-order_test.sh: pass
…llGate#839 The reader tolerance (hasTollGateSSID trimming at most one leading '!' before the case-insensitive brand-prefix compare) is carried by OpenTollGate#839 (fix/706-ssid-reader-tolerance, split out of OpenTollGate#775). Both PRs modify src/wireless_gateway_manager/brands.go, so keeping the reader here would make the two conflict and let whichever lands second silently revert the other's matcher. One writer, one reader, no overlap. Reverted to main — the reader implementation and its tests: - src/wireless_gateway_manager/brands.go - src/wireless_gateway_manager/brands_test.go - src/wireless_gateway_manager/reseller_mode_test.go The last one is not a "brands*.go" file but is reader-side all the same: it adds a `!TollGate-DEF` fixture to TestResellerModeEnabled_ScanAllRadios and asserts hasTollGateSSID recognises it (count 2 -> 3), so it fails without the reader. Note for OpenTollGate#839: it does not carry that reseller-mode coverage, so the decorated-SSID-selected-as-upstream assertion still has to land somewhere. Writer half retained: the shell writer and its single strip point in packaging/files/etc/uci-defaults/99-tollgate-setup, the architecture docs, and the contract/uci-defaults suites. Net diff is now writer-only (no src/ changes at all). Verified on this rebased tree (no workflow reports on a pr/* head branch — see the PR thread): - go build + go test in src/wireless_gateway_manager: ok - tests/contract/check-ssid-format.sh: pass - tests/uci-defaults-device-code_test.sh: 89 passed, 0 failed - tests/uci-defaults-gatewayname-banner_test.sh: 21 passed, 0 failed - tests/uci-defaults-setup-marker-order_test.sh: pass
|
🏷️ Next action — changes-requested Changes requested — author addresses the blocking item(s) in the review above, then request a re-review. |
c0a7327 to
053b157
Compare
c03rad0r
left a comment
There was a problem hiding this comment.
Cross-identity review — drift-fences-767
What it does. Four CI/pre-commit drift fences: fragment→real-PR/issue identity (with an online existence check), go.mod toolchain ceiling vs the manifest pin, the SSID matcher acceptance table, and a pristine-container module-suite lane with a fail-closed known-issues gate.
Read of the substance. Each fence maps to a failure that already happened (#704's numberless fragment, #631/#743 foreign links, #618/#706 SSID reader/writer splits, host-clean-only suite failures), which is the right justification. Executing both sides and comparing is the doctrine.
Worth noting.
- The clean-container known-issues list is "meant to shrink" but nothing enforces that. A tolerated-failures list that may grow silently becomes a de-facto allowlist; add a check that it does not grow (compare against the committed length, fail on additions) or the lane degrades into decoration.
- The fragment-identity fence needs network for the online existence check. Make the offline path fail clearly rather than skip, or a GitHub outage will silently exempt foreign links.
Disposition: land-with-followups (the known-issues-growth guard and the offline behaviour of the online check).
…ment identity, toolchain ceiling, SSID matcher table, clean-container lane
053b157 to
c34ea92
Compare
Amperstrand
left a comment
There was a problem hiding this comment.
Pre-review with evidence — four drift fences. Rebased onto post-rc2 main; on the rebased tree: check-ssid-naming.sh PASS, wireless_gateway_manager vet clean (full suite green at original validation). Fences carry planted-drift verdicts per doctrine. One-click approval candidate.
|
Scope note (#909): this PR is quality/docs, not on the 0.6.0 critical path — the earlier 'one-click approval' staging stands, but there is no release urgency; approve at leisure or let it ride 0.6.1. Keeping the evidence review attached for whenever it's reviewed. |
Review —
|
felixfelix-bot
left a comment
There was a problem hiding this comment.
Changes requested at c34ea92842c98cf2710d3d9791503657e0eea031 — the fragment-identity fence fails on its own tree (4 findings, verified), plus an unrelated CI-step deletion. Details in the summary comment.
Trigger/gating-level only; no job bodies rewritten. test.yml gains PR concurrency cancellation; its spec-quote step becomes a push-only job (pip-from-git + nuts-fetch preamble no longer runs per PR); the 45-minute happy-path moves to .github/workflows/happy-path.yml with a paths filter that keeps it gating every runtime-affecting PR (doctrine unchanged: a PR that breaks the happy path is the PR that goes red) while docs- and tests-only PRs skip it. build-package's ~22-job PR matrix now runs only for packaging-affecting paths; repro-check and router-test become merge-time (push/dispatch); gitleaks goes daily -> weekly. On a public repo this saves ~zero metered minutes — the wins are queue latency, runner availability under org concurrency caps, and frugality habits that matter the day the org loses public-repo freebies. Landed now deliberately: workflows are inert until #790's org switch flips, so restructuring carries zero mid-flight risk. The ngit twin is untouched (its runner cost is lab infra, not GitHub's). Known trivial conflict with open #775 (clean-container job inserts where the happy-path block moved from) — both branches are mine to reconcile. Refs #816
Local CI gate — PR #775: test(contract): four drift fences — fragment identity, toolchain ceiling, SSID matcher table, clean-container laneRun of
Verdict: 1 leg(s) RED — 5 green. What this gate does not run (no vacuous green)
failing-leg log tailsshell-suites — tail |
Closes #767. Four fences, four commits, off current
main(4614ac2).What
Changelog fragment identity (
check-changelog-fragments.py+ verdicts harness). Everychangelog.d/*.mdmust name its own change: a real PR/issue number in the filename, that same number referenced in the body, no markdown link to a foreign PR (the docs(wallet): derive NUT-07/NUT-09 for any bearer instrument (research + runnable demo) #631/fix(config,cli): durable config writes + offline wallet.db corruption check (#505 audit) #743 paste class), no placeholder text (TBD/TODO/#NNN/<pr>/0-; inline-code spans quoting the naming grammar are exempt — the feat(changelog): fragments instead of per-PR CHANGELOG hunks — the conflicts stop existing #679 fragment caught that false positive during development). CI runs it offline AND--online(every referenced number verified to exist via gh/urllib); pre-commit runs offline. Live specimen repaired:vm-campaign.added.mdcarried no number at all — renamed to704-vm-campaign.added.mdwith its PR link.Toolchain ceiling (
check-toolchain-parity.pyextended + verdicts harness). Everygo.modgodirective must be <= the manifest's.go.version(a floor above the pinned toolchain cannot compile in the SDK lane), and workflowcontainer: golang:<tag>pins must match the manifest likego-version:pins already do. Workflow scan now covers the.ngittwin (all its pins are expression-derived, so green).--rootmakes the checker fixture-testable. Today: 19 modules, max directive 1.26.0 <= 1.26.8.SSID matcher acceptance table (
check-ssid-naming.sh+ committed fixture file).hasTollGateSSIDmust accept both brands, bare AND single-!-decorated, case-insensitively, and reject a double!— one table (tests/contract/ssid-naming-fixtures.txt) drives both the Go unit test (behaviour) and the contract check (structure + wiring). The SSID contract broke twice (fix(discovery): recognize both brands' SSIDs so Net4sats can be an upstream #618 brand-blind matcher, feat(ssid)!: the captive SSID carries a leading '!' so it sorts first #706 decoration): each was a reader/writer disagreement this table would have caught. The whitelabel literal lives only in the fixture file — its allowlisted home in the rebrand gutter (same exemption ascheck-ssid-format.sh); Go source keeps assembling it from non-contiguous bytes.Note — this lands feat(ssid)!: the captive SSID carries a leading '!' so it sorts first #706's reader-side tolerance (trim at most one
!, per feat(ssid)!: the captive SSID carries a leading '!' so it sorts first #706's own design): a runtime superset, so!TollGate-*upstreams are recognized by this module even before feat(ssid)!: the captive SSID carries a leading '!' so it sorts first #706's writer half lands. feat(ssid)!: the captive SSID carries a leading '!' so it sorts first #706 then only needs its writer/installer side; its cross-version caveat stands (older reseller routers still match bare prefixes only until upgraded).Clean-container lane (
clean-container-testjob + fail-closed gate). The module suite in pristinegolang:1.26.8-bookworm(tag parity-checked like any pin). A test green on ubuntu-latest but red there is coupled to host state — the/etc/tollgateclass, $HOME leftovers, runner packages, warm caches. Gate contract mirrors the happy-path gate: failures are fatal unless listed intests/contract/clean-container-known-issues.txtwith an open issue; build/harness failures always fatal; stale entries flagged. ngit twin deliberately absent (ngit-ci refusescontainer:).Plus:
hooks/pre-commitwiring for all of it (fragment identity on changelog.d, parity on go.mod, SSID naming on brands/fixture paths), both workflow twins updated where their jobs exist, andchangelog.d/767-contract-drift-fences.internal.md.Verification
make go-battery: 15/16 modules green;src/merchantcarries the two pre-existing, filed failures of plainmain(merchant suite: TestLateReceiveOutcomeIsRecordedWhenReceiveCompletesAfterTheDeadline fails in every full-package run (passes in isolation) — record picker grabs the owed-grant ERROR line #731 — order-dependent, and merchant: TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow fails deterministically off-router — grant-side ndsctl exec is never stubbed #772 — deterministic off-router, filed from this work: the duplicate-guard test never stubs the grant-sidendsctlexec). Neither is touched by this diff; the fix for merchant: TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow fails deterministically off-router — grant-side ndsctl exec is never stubbed #772 is already visible as a one-liner on the merchant session's branch (ec759a0) — cross-referenced on the issue.env -i, fresh HOME/GOPATH/GOCACHE, clean worktree — all ten lanes green except the two filed merchant tests, tolerated with their issues; the gate exited 0. The first CI run is the true container proof (bookworm libc vs this host's); if it diverges, that is itself a finding per the lane's charter.brands.go's tolerance change is logic-level, verified by the fixture-driven unit test under-raceonly.@felixfelix-bot — requesting cross-identity approval: what = four CI/pre-commit drift fences for the contract estate (fragment→real-PR/issue identity incl. online existence check; go.mod ceiling vs the manifest pin; pinned SSID-matcher acceptance table for both brands × bare/
!-decorated × case, double-!rejected — landing #706's reader half; pristine-container module-suite lane with a fail-closed, meant-to-shrink known-issues gate); why = each fence's failure class already happened (#704's numberless fragment, #631/#743-class foreign links, #618/#706 SSID reader/writer splits, and suite failures that only reproduce where the host is clean) and today nothing notices any of them automatically.